In [1]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()
import warnings
warnings.filterwarnings("ignore")
import matplotlib
%matplotlib inline
import fbprophet #for time series modeling and forecasting
from fbprophet import Prophet
from fbprophet.plot import plot_plotly
import plotly.offline as py
py.init_notebook_mode()
import plotly.graph_objects as go
import plotly.express as px 

plt.style.use('fivethirtyeight')
matplotlib.rcParams['axes.labelsize'] = 14
matplotlib.rcParams['xtick.labelsize'] = 12
matplotlib.rcParams['ytick.labelsize'] = 12
matplotlib.rcParams['text.color'] = 'k'

import sys

!{sys.executable} -m pip install quandl

Installed fbprophet package through powershell prompt

Required MIcrosoft visual c++ tool 14.0

In [2]:
DAL = pd.read_csv('DAL.csv')    #Delta
AAL = pd.read_csv('AAL.csv')    #American
LUV = pd.read_csv('LUV.csv')    #SouthWest
UAL = pd.read_csv('UAL.csv')    #United
In [4]:
AAL.tail(5)
Out[4]:
Date Open High Low Close Adj Close Volume
3285 5/21/2020 9.87 10.15 9.83 9.89 9.89 45785700
3286 5/22/2020 10.02 10.12 9.63 9.70 9.70 37596800
3287 5/26/2020 10.27 11.28 10.25 11.14 11.14 101717000
3288 5/27/2020 12.43 12.55 11.07 11.98 11.98 99314800
3289 5/28/2020 11.78 11.83 10.90 10.98 10.98 70488800
In [5]:
plt.figure(figsize = (24,12))
plt.plot(range(DAL.shape[0]),(DAL['Low']+DAL['High'])/2.0, 'b-', label = 'Delta')
plt.plot(range(AAL.shape[0]),(AAL['Low']+AAL['High'])/2.0, 'r-', label = 'American')
plt.plot(range(LUV.shape[0]),(LUV['Low']+LUV['High'])/2.0, 'g-', label = 'SouthWest')
plt.plot(range(UAL.shape[0]),(UAL['Low']+UAL['High'])/2.0, 'y-', label = 'United')
plt.xticks(range(0,DAL.shape[0],500),DAL['Date'].loc[::500],rotation=45)
plt.xlabel('Date',fontsize=18)
plt.ylabel('Mid Price',fontsize=18)
plt.title('Trends in the 4 Airlines Stock Prices over 13 year')
plt.legend();
In [3]:
#Data Visualization
##Exploring the patterns occuring over time
plt.figure(figsize = (18,9))
plt.plot(range(DAL.shape[0]),(DAL['Low']+DAL['High'])/2.0)
plt.xticks(range(0,DAL.shape[0],500),DAL['Date'].loc[::500],rotation=45)
plt.xlabel('Date',fontsize=18)
plt.ylabel('Mid Price',fontsize=18)
plt.title('Trends in Delta Airlines Stock Prices over 13 year')
plt.show()

plt.figure(figsize = (18,9))
plt.plot(range(AAL.shape[0]),(AAL['Low']+AAL['High'])/2.0,'r')
plt.xticks(range(0,AAL.shape[0],500),AAL['Date'].loc[::500],rotation=45)
plt.xlabel('Date',fontsize=18)
plt.ylabel('Mid Price',fontsize=18)
plt.title('Trends in American Airlines Stock Prices over 13 year')
plt.show()

plt.figure(figsize = (18,9))
plt.plot(range(LUV.shape[0]),(LUV['Low']+LUV['High'])/2.0,'g')
plt.xticks(range(0,LUV.shape[0],500),LUV['Date'].loc[::500],rotation=45)
plt.xlabel('Date',fontsize=18)
plt.ylabel('Mid Price',fontsize=18)
plt.title('Trends in SouthWest Airlines Stock Prices over 13 year')
plt.show()

plt.figure(figsize = (18,9))
plt.plot(range(UAL.shape[0]),(UAL['Low']+UAL['High'])/2.0,'y')
plt.xticks(range(0,UAL.shape[0],500),UAL['Date'].loc[::500],rotation=45)
plt.xlabel('Date',fontsize=18)
plt.ylabel('Mid Price',fontsize=18)
plt.title('Trends in United Airlines Stock Prices over 13 year')
plt.show()
In [7]:
DAL['Date'] = pd.to_datetime(DAL['Date'])
DAL['Year'] = DAL['Date'].dt.year

AAL['Date'] = pd.to_datetime(AAL['Date'])
AAL['Year'] = AAL['Date'].dt.year
DAL.tail(5)
Out[7]:
Date Open High Low Close Adj Close Volume Year
3285 2020-05-21 22.77 23.680000 22.670000 23.160000 23.160000 46567200 2020
3286 2020-05-22 23.24 23.400000 22.230000 22.690001 22.690001 37139300 2020
3287 2020-05-26 24.48 25.870001 24.280001 25.650000 25.650000 78557100 2020
3288 2020-05-27 27.67 27.850000 24.730000 26.320000 26.320000 92712000 2020
3289 2020-05-28 26.25 26.360001 24.950001 25.660000 25.660000 53868100 2020
In [8]:
LUV['Date'] = pd.to_datetime(LUV['Date'])
LUV['Year'] = LUV['Date'].dt.year

UAL['Date'] = pd.to_datetime(UAL['Date'])
UAL['Year'] = UAL['Date'].dt.year
UAL.head(5)
Out[8]:
Date Open High Low Close Adj Close Volume Year
0 2007-05-04 33.900002 35.759998 33.799999 35.570000 33.263046 4449500 2007
1 2007-05-07 36.700001 36.700001 35.080002 35.470001 33.169533 3722000 2007
2 2007-05-08 35.029999 36.470001 35.000000 35.779999 33.459427 2182900 2007
3 2007-05-09 35.740002 36.180000 35.070000 35.250000 32.963802 3354200 2007
4 2007-05-10 34.990002 35.490002 34.500000 34.610001 32.365311 2429400 2007
In [6]:
from pandas import *
xls = ExcelFile('Shares.xlsx')
data = xls.parse(xls.sheet_names[0])
print(data['UAL'].to_dict())
{0: 249, 1: 260, 2: 277, 3: 304, 4: 330, 5: 377, 6: 390, 7: 391, 8: 331, 9: 383, 10: 253, 11: 151, 12: 127, 13: 151}
In [9]:
# Yearly average number of shares outstanding for Delta and American Airlines
        ##For year 2020 only first quarter data
dal_shares = {2020: 637e6, 2019: 653e6, 2018: 694e6, 2017: 723e6, 2016: 755e6, 2015: 804e6, 2014: 845e6, 
                2013: 858e6, 2012: 850e6, 2011: 844e6, 2010: 843e6, 2009: 827e6, 2008: 468e6, 2007: 395e6}

aal_shares = {2020: 426e6, 2019: 444e6, 2018: 466e6, 2017: 492e6, 2016: 556e6, 2015: 687e6, 2014: 734e6, 
                2013: 280e6, 2012: 249e6, 2011: 125e6, 2010: 333e6, 2009: 294e6, 2008: 259e6, 2007: 267e6}

luv_shares = {2020: 515e6, 2019: 539e6, 2018: 574e6, 2017: 603e6, 2016: 633e6, 2015: 669e6, 2014: 696e6, 
                2013: 718e6, 2012: 757e6, 2011: 775e6, 2010: 747e6, 2009: 741e6, 2008: 739e6, 2007: 768e6}

ual_shares = {2020: 249e6, 2019: 260e6, 2018: 277e6, 2017: 304e6, 2016: 330e6, 2015: 377e6, 2014: 390e6, 
                2013: 391e6, 2012: 331e6, 2011: 383e6, 2010: 253e6, 2009: 151e6, 2008: 127e6, 2007: 151e6}
In [10]:
# Take Dates from index and move to Date column 
DAL.reset_index(level=0, inplace = True)
# Take Dates from index and move to Date column 
AAL.reset_index(level=0, inplace = True)
# Take Dates from index and move to Date column 
LUV.reset_index(level=0, inplace = True)
# Take Dates from index and move to Date column 
UAL.reset_index(level=0, inplace = True)
In [11]:
#Calculate Market Capitalization
#Delta
DAL['cap'] = 0

# Calculate market cap for all years
for i, year in enumerate(DAL['Year']):
    # Retrieve the shares for the year
    shares = dal_shares.get(year)
    
    # Update the cap column to shares times the price
    DAL.ix[i, 'cap'] = shares * DAL.ix[i, 'Adj Close']
    
#American
AAL['cap'] = 0

# Calculate market cap for all years
for i, year in enumerate(AAL['Year']):
    # Retrieve the shares for the year
    shares = aal_shares.get(year)
    
    # Update the cap column to shares times the price
    AAL.ix[i, 'cap'] = shares * AAL.ix[i, 'Adj Close']

#SouthWest
LUV['cap'] = 0

# Calculate market cap for all years
for i, year in enumerate(LUV['Year']):
    # Retrieve the shares for the year
    shares = luv_shares.get(year)
    
    # Update the cap column to shares times the price
    LUV.ix[i, 'cap'] = shares * LUV.ix[i, 'Adj Close']
    
#United
UAL['cap'] = 0

# Calculate market cap for all years
for i, year in enumerate(UAL['Year']):
    # Retrieve the shares for the year
    shares = ual_shares.get(year)
    
    # Update the cap column to shares times the price
    UAL.ix[i, 'cap'] = shares * UAL.ix[i, 'Adj Close']
In [12]:
UAL.head(5)
Out[12]:
index Date Open High Low Close Adj Close Volume Year cap
0 0 2007-05-04 33.900002 35.759998 33.799999 35.570000 33.263046 4449500 2007 5.022720e+09
1 1 2007-05-07 36.700001 36.700001 35.080002 35.470001 33.169533 3722000 2007 5.008599e+09
2 2 2007-05-08 35.029999 36.470001 35.000000 35.779999 33.459427 2182900 2007 5.052373e+09
3 3 2007-05-09 35.740002 36.180000 35.070000 35.250000 32.963802 3354200 2007 4.977534e+09
4 4 2007-05-10 34.990002 35.490002 34.500000 34.610001 32.365311 2429400 2007 4.887162e+09

Visualizing Market CAP of the four Airlines

In [13]:
# Merge the two datasets and rename the columns
airlines1 = DAL.merge(AAL, how='inner', on='Date')
airlines2 = LUV.merge(UAL, how='inner',on='Date')

#Changing the names for merge
airlines1.rename(columns={'cap_x': 'DAL_cap', 'cap_y': 'AAL_cap'}, inplace=True)
airlines2.rename(columns={'cap_x': 'LUV_cap', 'cap_y': 'UAL_cap'}, inplace=True)
#from functools import reduce
#data_frames= [DAL, AAL, LUV, UAL]
#airlines = reduce(lambda left, right: pd.merge(left, right,on=['Date'],how='inner'),data_frames)
print(airlines1.columns)
print(airlines2.columns)
Index(['index_x', 'Date', 'Open_x', 'High_x', 'Low_x', 'Close_x',
       'Adj Close_x', 'Volume_x', 'Year_x', 'DAL_cap', 'index_y', 'Open_y',
       'High_y', 'Low_y', 'Close_y', 'Adj Close_y', 'Volume_y', 'Year_y',
       'AAL_cap'],
      dtype='object')
Index(['index_x', 'Date', 'Open_x', 'High_x', 'Low_x', 'Close_x',
       'Adj Close_x', 'Volume_x', 'Year_x', 'LUV_cap', 'index_y', 'Open_y',
       'High_y', 'Low_y', 'Close_y', 'Adj Close_y', 'Volume_y', 'Year_y',
       'UAL_cap'],
      dtype='object')
In [14]:
airlines = airlines1.merge(airlines2, how='inner', on='Date')
In [15]:
# Select only the relevant columns
airlines = airlines.ix[:, ['Date', 'DAL_cap', 'AAL_cap','LUV_cap','UAL_cap']]

# Divide to get market cap in billions of dollars
airlines['DAL_cap'] = airlines['DAL_cap'] / 1e9
airlines['AAL_cap'] = airlines['AAL_cap'] / 1e9
airlines['LUV_cap'] = airlines['LUV_cap'] / 1e9
airlines['UAL_cap'] = airlines['UAL_cap'] / 1e9
airlines.head()
Out[15]:
Date DAL_cap AAL_cap LUV_cap UAL_cap
0 2007-05-04 7.361441 9.099388 10.410040 5.022720
1 2007-05-07 7.143898 8.837607 10.459679 5.008599
2 2007-05-08 6.887754 8.658893 10.417128 5.052373
3 2007-05-09 6.943895 8.643788 10.310759 4.977534
4 2007-05-10 6.912318 8.376974 10.154751 4.887162
In [16]:
plt.figure(figsize=(24, 12))
plt.plot(airlines['Date'], airlines['DAL_cap'], 'b-', label = 'DAL')
plt.plot(airlines['Date'], airlines['AAL_cap'], 'r-', label = 'AAL')
plt.plot(airlines['Date'], airlines['LUV_cap'], 'g-', label = 'LUV')
plt.plot(airlines['Date'], airlines['UAL_cap'], 'y-', label = 'UAL')
plt.xlabel('Date'); plt.ylabel('Market Cap (Billions $)'); plt.title('Market Cap of Delta, America, Southwest and United Airlines')
plt.legend();
In [17]:
plt.figure(figsize=(10, 8))
plt.plot(airlines['Date'], airlines['DAL_cap'], 'b-', label = 'DAL')
plt.plot(airlines['Date'], airlines['LUV_cap'], 'g-', label = 'LUV')
plt.xlabel('Date'); plt.ylabel('Market Cap (Billions $)'); plt.title('Market Cap of Delta and Southwest Airlines')
plt.legend();
In [18]:
plt.figure(figsize=(10, 8))
plt.plot(airlines['Date'], airlines['AAL_cap'], 'r-', label = 'AAL')
plt.plot(airlines['Date'], airlines['UAL_cap'], 'y-', label = 'UAL')
plt.xlabel('Date'); plt.ylabel('Market Cap (Billions $)'); plt.title('Market Cap of America and United Airlines')
plt.legend();

American Airlines briefly surpassed Delta Airlines in market cap in 2015. From 2008, financial crisis onwards AA couldn't perform better than DA.

It is also worth noticing in the year 2020, though both industry has seen a decline due to COVID-19 pandemic, but the Delta Airlines stocks and market cap has plummeted more than American Airlines.

* Can this be a twist or an opportunity for American Airlines?
In [19]:
# Find the first and last time LUV was valued higher than DAL
first_date = airlines.ix[np.min(list(np.where(airlines['LUV_cap'] > airlines['DAL_cap'])[0])), 'Date']
last_date = airlines.ix[np.max(list(np.where(airlines['LUV_cap'] > airlines['DAL_cap'])[0])), 'Date']

print("LUV was valued higher than DAL on {} and {}.".format(first_date.date(), last_date.date()))
LUV was valued higher than DAL on 2007-05-04 and 2020-05-28.
In [20]:
# Find the first and last time AAL was valued higher than UAL
first_date = airlines.ix[np.min(list(np.where(airlines['AAL_cap'] > airlines['UAL_cap'])[0])), 'Date']
last_date = airlines.ix[np.max(list(np.where(airlines['AAL_cap'] > airlines['UAL_cap'])[0])), 'Date']

print("AAL was valued higher than UAL on {} and {}.".format(first_date.date(), last_date.date()))
AAL was valued higher than UAL on 2007-05-04 and 2018-06-11.

Note

  1. In the U.S., the big three carriers of American, Delta and United have all slashed their schedules as passenger traffic has dried up. This has also led to the early retirement of American Airlines Boeing 767s and 757s and Delta Airlines 777s. The carriers also have cut domestic flights, as have other airlines, including Southwest, Alaska and JetBlue.
In [21]:
# Prophet requires columns ds (Date) and y (value)
DAL = DAL.rename(columns={'Date': 'ds', 'cap': 'y'})
AAL = AAL.rename(columns={'Date': 'ds', 'cap': 'y'})
LUV = LUV.rename(columns={'Date': 'ds', 'cap': 'y'})
UAL = UAL.rename(columns={'Date': 'ds', 'cap': 'y'})

# Put market cap in billions
DAL['y'] = DAL['y'] / 1e9
AAL['y'] = AAL['y'] / 1e9
LUV['y'] = LUV['y'] / 1e9
UAL['y'] = UAL['y'] / 1e9

Entire data model

In [22]:
# Make the prophet models and fit on the data
# changepoint_prior_scale can be changed to achieve a better fit
#D_Model1 = Prophet(changepoint_prior_scale=0.15, changepoints=['2020-03-16', '2020-05-15'])
D_Model1 = Prophet(changepoint_prior_scale=0.20)
D_Model1.fit(DAL)

##For next 60 days
dal_forecast = D_Model1.make_future_dataframe(periods=60, freq='D')
# Make predictions
dal_forecast = dal_forecast[dal_forecast['ds'].dt.dayofweek < 5]
dal_forecast = D_Model1.predict(dal_forecast)
INFO:fbprophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.
In [23]:
# Repeat for the 3 airlines data
#A_Model1 = Prophet(changepoint_prior_scale=0.15, changepoints=['2020-03-16','2020-04-15'], n_changepoints=10)
A_Model1 = Prophet(changepoint_prior_scale=0.20)
A_Model1.fit(AAL);

L_Model1 = Prophet(changepoint_prior_scale=0.20)
L_Model1.fit(LUV);

U_Model1 = Prophet(changepoint_prior_scale=0.20)
U_Model1.fit(UAL);
INFO:fbprophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.
INFO:fbprophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.
INFO:fbprophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.

Quarterly predictions

In [24]:
#Make Predictions
aal_forecast = A_Model1.make_future_dataframe(periods=60, freq='D')
aal_forecast = aal_forecast[aal_forecast['ds'].dt.dayofweek < 5]
aal_forecast = A_Model1.predict(aal_forecast)

luv_forecast = L_Model1.make_future_dataframe(periods=60, freq='D')
luv_forecast = luv_forecast[luv_forecast['ds'].dt.dayofweek < 5]
luv_forecast = L_Model1.predict(luv_forecast)

ual_forecast = U_Model1.make_future_dataframe(periods=60, freq='D')
ual_forecast = ual_forecast[ual_forecast['ds'].dt.dayofweek < 5]
ual_forecast = U_Model1.predict(ual_forecast)
In [25]:
def make_comparison_dataframe(historical, forecast):
    return forecast.set_index('ds')[['yhat', 'yhat_lower', 'yhat_upper']].join(historical.set_index('ds'))
In [26]:
 def calculate_forecast_errors(df, prediction_size):
       
    df = df.copy()
    
    df['e'] = df['y'] - df['yhat']
    df['p'] = 100 * df['e'] / df['y']
    
    predicted_part = df[-prediction_size:]
    
    error_mean = lambda error_name: np.mean(np.abs(predicted_part[error_name]))
    
    return {'MAPE': error_mean('p'), 'MAE': error_mean('e')}
In [27]:
#Plotting the forecast for the airlines
fig1 = go.Figure()
fig2 = go.Figure()
fig3 = go.Figure()
fig4 = go.Figure()

fig1 = plot_plotly(D_Model1, dal_forecast, xlabel = 'Date', ylabel = 'Market Cap (billions $)')
fig1.update_layout(title = 'Market cap forecast of Delta')
In [28]:
cmp_d = make_comparison_dataframe(DAL, dal_forecast)
cmp_d.tail()
Out[28]:
yhat yhat_lower yhat_upper index Open High Low Close Adj Close Volume Year y
ds
2020-07-21 30.132025 26.723074 33.485204 NaN NaN NaN NaN NaN NaN NaN NaN NaN
2020-07-22 30.103885 26.667122 33.460530 NaN NaN NaN NaN NaN NaN NaN NaN NaN
2020-07-23 30.091460 26.773444 33.487299 NaN NaN NaN NaN NaN NaN NaN NaN NaN
2020-07-24 30.135146 26.666498 33.214232 NaN NaN NaN NaN NaN NaN NaN NaN NaN
2020-07-27 30.050467 26.656361 33.741885 NaN NaN NaN NaN NaN NaN NaN NaN NaN
In [29]:
for err_name, err_value in calculate_forecast_errors(cmp_d, 60).items():
    print(err_name, err_value)
MAPE 109.50394543003436
MAE 15.303787977041347
In [30]:
fig2 = plot_plotly(L_Model1, luv_forecast, xlabel = 'Date', ylabel = 'Market Cap (billions $)')
fig2.update_layout(title = 'Market cap forecast of Southwest')
In [31]:
cmp_s = make_comparison_dataframe(LUV, luv_forecast)
#cmp_df.tail()
for err_name, err_value in calculate_forecast_errors(cmp_s, 60).items():
    print(err_name, err_value)
MAPE 59.32799373037923
MAE 8.198215494107645
In [32]:
fig3 = plot_plotly(A_Model1, aal_forecast, xlabel = 'Date', ylabel = 'Market Cap (billions $)')
fig3.update_layout(title = 'Market cap forecast of American')
In [33]:
cmp_a = make_comparison_dataframe(AAL, aal_forecast)
#cmp_df.tail()
for err_name, err_value in calculate_forecast_errors(cmp_a, 60).items():
    print(err_name, err_value)
MAPE 60.74842280371783
MAE 2.5239082705753297
In [34]:
fig4 = plot_plotly(U_Model1, ual_forecast, xlabel = 'Date', ylabel = 'Market Cap (billions $)')
fig4.update_layout(title = 'Market cap forecast of United')
In [35]:
cmp_u = make_comparison_dataframe(UAL, ual_forecast)
#cmp_df.tail()
for err_name, err_value in calculate_forecast_errors(cmp_u, 60).items():
    print(err_name, err_value)
MAPE 188.7017282624341
MAE 11.292429599137778

Entire data with train and test split

In [36]:
#Hold-out 30 observations
size = 30

train_df = DAL[:-size]
D_Model4 = Prophet(changepoint_prior_scale=0.20)   
D_Model4.fit(train_df)

train_df = AAL[:-size]
A_Model4 = Prophet(changepoint_prior_scale=0.20)   
A_Model4.fit(train_df)

train_df = LUV[:-size]
L_Model4 = Prophet(changepoint_prior_scale=0.20)   
L_Model4.fit(train_df)

train_df = UAL[:-size]
U_Model4 = Prophet(changepoint_prior_scale=0.20)   
U_Model4.fit(train_df)


##For next 60 days
dal3_forecast = D_Model4.make_future_dataframe(periods=60, freq='D')
# Make predictions
dal3_forecast = dal3_forecast[dal3_forecast['ds'].dt.dayofweek < 5]
dal3_forecast = D_Model4.predict(dal3_forecast)

aal3_forecast = A_Model4.make_future_dataframe(periods=60, freq='D')
# Make predictions
aal3_forecast = aal3_forecast[aal3_forecast['ds'].dt.dayofweek < 5]
aal3_forecast = A_Model4.predict(aal3_forecast)

luv3_forecast = L_Model4.make_future_dataframe(periods=60, freq='D')
# Make predictions
luv3_forecast = luv3_forecast[luv3_forecast['ds'].dt.dayofweek < 5]
luv3_forecast = L_Model4.predict(luv3_forecast)

ual3_forecast = U_Model4.make_future_dataframe(periods=60, freq='D')
# Make predictions
ual3_forecast = ual3_forecast[ual3_forecast['ds'].dt.dayofweek < 5]
ual3_forecast = U_Model4.predict(ual3_forecast)
INFO:fbprophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.
INFO:fbprophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.
INFO:fbprophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.
INFO:fbprophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.
In [37]:
#Plotting the forecast for the airlines
fig1 = go.Figure()
fig2 = go.Figure()
fig3 = go.Figure()
fig4 = go.Figure()

fig1 = plot_plotly(D_Model4, dal3_forecast, xlabel = 'Date', ylabel = 'Market Cap (billions $)')
fig1.update_layout(title = 'Market cap forecast of Delta')
In [38]:
fig2 = plot_plotly(L_Model4, luv3_forecast, xlabel = 'Date', ylabel = 'Market Cap (billions $)')
fig2.update_layout(title = 'Market cap forecast of Southwest')
In [39]:
fig3 = plot_plotly(A_Model4, aal_forecast, xlabel = 'Date', ylabel = 'Market Cap (billions $)')
fig3.update_layout(title = 'Market cap forecast of American')
In [40]:
fig4 = plot_plotly(U_Model4, ual_forecast, xlabel = 'Date', ylabel = 'Market Cap (billions $)')
fig4.update_layout(title = 'Market cap forecast of United')
In [41]:
cmp_d3 = make_comparison_dataframe(DAL, dal3_forecast)
for err_name, err_value in calculate_forecast_errors(cmp_d3, 60).items():
    print(err_name, err_value)
    
cmp_a3 = make_comparison_dataframe(AAL, aal3_forecast)
for err_name, err_value in calculate_forecast_errors(cmp_a3, 60).items():
    print(err_name, err_value)
    
cmp_l3 = make_comparison_dataframe(LUV, luv3_forecast)
for err_name, err_value in calculate_forecast_errors(cmp_l3, 60).items():
    print(err_name, err_value)
    
cmp_u3 = make_comparison_dataframe(UAL, ual3_forecast)
for err_name, err_value in calculate_forecast_errors(cmp_u3, 60).items():
    print(err_name, err_value)
MAPE 121.37875543091177
MAE 17.90523708484135
MAPE 73.85421939253554
MAE 3.3336243277727537
MAPE 58.121155430718716
MAE 8.828499293073113
MAPE 209.40214466921944
MAE 13.63441751776241
In [42]:
#Data from Feb 03, 2020 to May 28,2020 to check COVID-19 impact
#For running various variations
start_date = '02-03-2020'
end_date = '05-28-2020'
mask = (DAL['ds'] > start_date) & (DAL['ds'] <= end_date)
DAL1 = DAL.loc[mask]
mask = (AAL['ds'] > start_date) & (AAL['ds'] <= end_date)
AAL1 = AAL.loc[mask]
mask = (LUV['ds'] > start_date) & (LUV['ds'] <= end_date)
LUV1 = LUV.loc[mask]
mask = (UAL['ds'] > start_date) & (UAL['ds'] <= end_date)
UAL1 = UAL.loc[mask]
print(DAL1.shape)
print (AAL1.shape)
(80, 10)
(80, 10)
In [45]:
#DAL1.reset_index(level=0, inplace = True)
DAL1.tail()
Out[45]:
index ds Open High Low Close Adj Close Volume Year y
3285 3285 2020-05-21 22.77 23.680000 22.670000 23.160000 23.160000 46567200 2020 14.752920
3286 3286 2020-05-22 23.24 23.400000 22.230000 22.690001 22.690001 37139300 2020 14.453531
3287 3287 2020-05-26 24.48 25.870001 24.280001 25.650000 25.650000 78557100 2020 16.339050
3288 3288 2020-05-27 27.67 27.850000 24.730000 26.320000 26.320000 92712000 2020 16.765840
3289 3289 2020-05-28 26.25 26.360001 24.950001 25.660000 25.660000 53868100 2020 16.345420
In [45]:
plt.figure(figsize = (24,12))
plt.plot(DAL1['ds'],DAL1['y'], 'b-', label = 'Delta')
plt.plot(AAL1['ds'],AAL1['y'], 'r-', label = 'American')
plt.plot(LUV1['ds'],LUV1['y'], 'g-', label = 'SouthWest')
plt.plot(UAL1['ds'],UAL1['y'], 'y-', label = 'United')
#plt.xticks(range(0,DAL.shape[0],500),DAL['Date'].loc[::500],rotation=45)
plt.xlabel('Date',fontsize=18)
plt.ylabel('Market Cap',fontsize=18)
plt.title('Trends in the 4 Airlines Market Cap amidst Covid-19 pandemic')
plt.legend();
In [46]:
plt.figure(figsize = (18,9))
plt.plot(DAL1['ds'],DAL1['y'])
plt.xlabel('Date',fontsize=18)
plt.ylabel('Mid Price',fontsize=18)
plt.title('Trends in Delta Airlines Stocks Prices amidst Covid-19 pandemic')
plt.show()

plt.figure(figsize = (18,9))
plt.plot(AAL1['ds'],AAL1['y'],'r')
plt.xlabel('Date',fontsize=18)
plt.ylabel('Mid Price',fontsize=18)
plt.title('Trends in American Airlines Stocks Prices amidst Covid-19 pandemic')
plt.show()

plt.figure(figsize = (18,9))
plt.plot(LUV1['ds'],LUV1['y'],'g')
plt.xlabel('Date',fontsize=18)
plt.ylabel('Mid Price',fontsize=18)
plt.title('Trends in SouthWest Airlines Stocks Prices amidst Covid-19 pandemic')
plt.show()

plt.figure(figsize = (18,9))
plt.plot(UAL1['ds'],UAL1['y'],'y')
plt.xlabel('Date',fontsize=18)
plt.ylabel('Mid Price',fontsize=18)
plt.title('Trends in United Airlines Stocks Prices amidst Covid-19 pandemic')
plt.show()
In [47]:
import logging

logging.getLogger().setLevel(logging.ERROR)
In [48]:
#Covid 19 
size = 30
train_df = DAL1[:-size]
In [49]:
D_Model2 = Prophet(changepoint_prior_scale=0.20)   
D_Model2.fit(train_df)

train_df = AAL1[:-size]
A_Model2 = Prophet(changepoint_prior_scale=0.20)   
A_Model2.fit(train_df)

train_df = LUV1[:-size]
L_Model2 = Prophet(changepoint_prior_scale=0.20)   
L_Model2.fit(train_df)

train_df = UAL1[:-size]
U_Model2 = Prophet(changepoint_prior_scale=0.20)   
U_Model2.fit(train_df)
INFO:fbprophet:Disabling yearly seasonality. Run prophet with yearly_seasonality=True to override this.
INFO:fbprophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.
INFO:fbprophet:Disabling yearly seasonality. Run prophet with yearly_seasonality=True to override this.
INFO:fbprophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.
INFO:fbprophet:Disabling yearly seasonality. Run prophet with yearly_seasonality=True to override this.
INFO:fbprophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.
INFO:fbprophet:Disabling yearly seasonality. Run prophet with yearly_seasonality=True to override this.
INFO:fbprophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.
Out[49]:
<fbprophet.forecaster.Prophet at 0x1755aecee48>
In [50]:
##For next 60 days
dal1_forecast = D_Model2.make_future_dataframe(periods=60, freq='D')
# Make predictions
dal1_forecast = dal1_forecast[dal1_forecast['ds'].dt.dayofweek < 5]
dal1_forecast = D_Model2.predict(dal1_forecast)

aal1_forecast = A_Model2.make_future_dataframe(periods=60, freq='D')
# Make predictions
aal1_forecast = aal1_forecast[aal1_forecast['ds'].dt.dayofweek < 5]
aal1_forecast = A_Model2.predict(aal1_forecast)

luv1_forecast = L_Model2.make_future_dataframe(periods=60, freq='D')
# Make predictions
luv1_forecast = luv1_forecast[luv1_forecast['ds'].dt.dayofweek < 5]
luv1_forecast = L_Model2.predict(luv1_forecast)

ual1_forecast = U_Model2.make_future_dataframe(periods=60, freq='D')
# Make predictions
ual1_forecast = ual1_forecast[ual1_forecast['ds'].dt.dayofweek < 5]
ual1_forecast = U_Model2.predict(ual1_forecast)
In [51]:
dal1_forecast.tail(10)
Out[51]:
ds trend yhat_lower yhat_upper trend_lower trend_upper additive_terms additive_terms_lower additive_terms_upper weekly weekly_lower weekly_upper multiplicative_terms multiplicative_terms_lower multiplicative_terms_upper yhat
82 2020-06-01 -9.079451 -4.054443 19.318331 -20.676150 2.018800 16.839788 16.839788 16.839788 16.839788 16.839788 16.839788 0.0 0.0 0.0 7.760337
83 2020-06-02 -9.219430 -4.407144 19.919914 -21.022590 2.250758 17.128201 17.128201 17.128201 17.128201 17.128201 17.128201 0.0 0.0 0.0 7.908771
84 2020-06-03 -9.359408 -4.687783 19.728413 -21.519105 2.551148 17.007061 17.007061 17.007061 17.007061 17.007061 17.007061 0.0 0.0 0.0 7.647652
85 2020-06-04 -9.499386 -6.294430 19.354630 -22.059159 2.769730 16.205601 16.205601 16.205601 16.205601 16.205601 16.205601 0.0 0.0 0.0 6.706214
86 2020-06-05 -9.639365 -5.982325 19.660572 -22.613658 3.047741 16.433965 16.433965 16.433965 16.433965 16.433965 16.433965 0.0 0.0 0.0 6.794600
87 2020-06-08 -10.059300 -7.737283 20.622958 -24.022300 3.821427 16.839788 16.839788 16.839788 16.839788 16.839788 16.839788 0.0 0.0 0.0 6.780488
88 2020-06-09 -10.199278 -7.690378 21.287780 -24.502681 4.067548 17.128201 17.128201 17.128201 17.128201 17.128201 17.128201 0.0 0.0 0.0 6.928923
89 2020-06-10 -10.339257 -8.283830 21.603633 -25.060598 4.279976 17.007061 17.007061 17.007061 17.007061 17.007061 17.007061 0.0 0.0 0.0 6.667804
90 2020-06-11 -10.479235 -9.654793 20.394738 -25.878351 4.557159 16.205601 16.205601 16.205601 16.205601 16.205601 16.205601 0.0 0.0 0.0 5.726366
91 2020-06-12 -10.619213 -10.338481 20.991608 -26.391660 4.975580 16.433965 16.433965 16.433965 16.433965 16.433965 16.433965 0.0 0.0 0.0 5.814751
In [52]:
fig5 = go.Figure()
fig5= plot_plotly(D_Model2, dal1_forecast, xlabel = 'Date', ylabel = 'Market Cap (billions $)')
fig5.update_layout(title = 'Market cap forecast of Delta')
In [53]:
D_Model2.plot_components(dal1_forecast)
Out[53]:
In [54]:
cmp_df = make_comparison_dataframe(DAL1, dal1_forecast)
cmp_df.tail()
Out[54]:
yhat yhat_lower yhat_upper index Open High Low Close Adj Close Volume Year y
ds
2020-06-08 6.780488 -7.737283 20.622958 NaN NaN NaN NaN NaN NaN NaN NaN NaN
2020-06-09 6.928923 -7.690378 21.287780 NaN NaN NaN NaN NaN NaN NaN NaN NaN
2020-06-10 6.667804 -8.283830 21.603633 NaN NaN NaN NaN NaN NaN NaN NaN NaN
2020-06-11 5.726366 -9.654793 20.394738 NaN NaN NaN NaN NaN NaN NaN NaN NaN
2020-06-12 5.814751 -10.338481 20.991608 NaN NaN NaN NaN NaN NaN NaN NaN NaN
In [55]:
for err_name, err_value in calculate_forecast_errors(cmp_df,60).items():
    print(err_name, err_value)
MAPE 18.19328462034482
MAE 2.747495161775968
In [56]:
fig6 = go.Figure()
fig6= plot_plotly(A_Model2, aal1_forecast, xlabel = 'Date', ylabel = 'Market Cap (billions $)')
fig6.update_layout(title = 'Market cap forecast of American')
In [57]:
cmp_a1 = make_comparison_dataframe(AAL1, aal1_forecast)
for err_name, err_value in calculate_forecast_errors(cmp_a1, 60).items():
    print(err_name, err_value)
MAPE 13.634179084195813
MAE 0.6402266149305958
In [58]:
fig7 = go.Figure()
fig7= plot_plotly(L_Model2, luv1_forecast, xlabel = 'Date', ylabel = 'Market Cap (billions $)')
fig7.update_layout(title = 'Market cap forecast of Southwest')
In [59]:
cmp_l1 = make_comparison_dataframe(LUV1, luv1_forecast)
for err_name, err_value in calculate_forecast_errors(cmp_l1, 60).items():
    print(err_name, err_value)
MAPE 8.792679542769589
MAE 1.333886982042752
In [60]:
fig8 = go.Figure()
fig8= plot_plotly(U_Model2, ual1_forecast, xlabel = 'Date', ylabel = 'Market Cap (billions $)')
fig8.update_layout(title = 'Market cap forecast of United')
In [61]:
cmp_a1 = make_comparison_dataframe(UAL1, ual1_forecast)
for err_name, err_value in calculate_forecast_errors(cmp_a1, 60).items():
    print(err_name, err_value)
MAPE 11.282693267773368
MAE 0.7368882657429271

Consider MAPE as it showed less error value when compared with other models Link https://mlcourse.ai/articles/topic9-part2-prophet/

Without Train test split

In [62]:
D_Model3 = Prophet(changepoint_prior_scale=0.20)   
D_Model3.fit(DAL1)

A_Model3 = Prophet(changepoint_prior_scale=0.20)   
A_Model3.fit(AAL1)

L_Model3 = Prophet(changepoint_prior_scale=0.20)   
L_Model3.fit(LUV1)

U_Model3 = Prophet(changepoint_prior_scale=0.20)   
U_Model3.fit(UAL1)

##For next 60 days
dal2_forecast = D_Model3.make_future_dataframe(periods=60, freq='D')
# Make predictions
dal2_forecast = dal2_forecast[dal2_forecast['ds'].dt.dayofweek < 5]
dal2_forecast = D_Model3.predict(dal2_forecast)

aal2_forecast = A_Model3.make_future_dataframe(periods=60, freq='D')
# Make predictions
aal2_forecast = aal2_forecast[aal2_forecast['ds'].dt.dayofweek < 5]
aal2_forecast = A_Model3.predict(aal2_forecast)

luv2_forecast = L_Model3.make_future_dataframe(periods=60, freq='D')
# Make predictions
luv2_forecast = luv2_forecast[luv2_forecast['ds'].dt.dayofweek < 5]
luv2_forecast = L_Model3.predict(luv2_forecast)

ual2_forecast = U_Model3.make_future_dataframe(periods=60, freq='D')
# Make predictions
ual2_forecast = ual2_forecast[ual2_forecast['ds'].dt.dayofweek < 5]
ual2_forecast = U_Model3.predict(ual2_forecast)
INFO:fbprophet:Disabling yearly seasonality. Run prophet with yearly_seasonality=True to override this.
INFO:fbprophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.
INFO:fbprophet:Disabling yearly seasonality. Run prophet with yearly_seasonality=True to override this.
INFO:fbprophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.
INFO:fbprophet:Disabling yearly seasonality. Run prophet with yearly_seasonality=True to override this.
INFO:fbprophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.
INFO:fbprophet:Disabling yearly seasonality. Run prophet with yearly_seasonality=True to override this.
INFO:fbprophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.
In [63]:
cmp_d2 = make_comparison_dataframe(DAL1, dal2_forecast)
for err_name, err_value in calculate_forecast_errors(cmp_d2, 60).items():
    print(err_name, err_value)
    
cmp_a2 = make_comparison_dataframe(AAL1, aal2_forecast)
for err_name, err_value in calculate_forecast_errors(cmp_a2, 60).items():
    print(err_name, err_value)
    
cmp_l2 = make_comparison_dataframe(LUV1, luv2_forecast)
for err_name, err_value in calculate_forecast_errors(cmp_l2, 60).items():
    print(err_name, err_value)
    
cmp_u2 = make_comparison_dataframe(UAL1, ual2_forecast)
for err_name, err_value in calculate_forecast_errors(cmp_u2, 60).items():
    print(err_name, err_value)
MAPE 7.21348710505524
MAE 1.005136194926584
MAPE 7.038630796577215
MAE 0.2976733754030507
MAPE 7.006594394582712
MAE 0.972114489337694
MAPE 10.397596639195294
MAE 0.6154010976353574
In [64]:
fig9 = go.Figure()
fig10 = go.Figure()
fig11 = go.Figure()
fig12 = go.Figure()

fig9 = plot_plotly(D_Model3, dal2_forecast, xlabel = 'Date', ylabel = 'Market Cap (billions $)')
fig9.update_layout(title = 'Market cap forecast of Delta')
In [65]:
fig10 = plot_plotly(A_Model3, aal2_forecast, xlabel = 'Date', ylabel = 'Market Cap (billions $)')
fig10.update_layout(title = 'Market cap forecast of American')
In [66]:
fig11 = plot_plotly(L_Model3, luv2_forecast, xlabel = 'Date', ylabel = 'Market Cap (billions $)')
fig11.update_layout(title = 'Market cap forecast of Southwest')
In [67]:
fig12 = plot_plotly(U_Model3, ual2_forecast, xlabel = 'Date', ylabel = 'Market Cap (billions $)')
fig12.update_layout(title = 'Market cap forecast of United')

U.S. Airlines suspended ALL flights between the U.S. and China On Friday, January 31, Delta, American and United announced they would temporarily suspend all of their mainland China flights in response to the coronavirus outbreak.[14]

Prior to this January 31 announcement:

UNITED AIRLINES on Jan. 28 had announced it would cut 24 flights between the U.S. and China for the first week of February. AMERICAN AIRLINES on Jan. 29 had announced it would suspend flights from Los Angeles to Shanghai and Beijing from Feb. 9 through March 27, 2020. It will maintain its flight schedules (10 daily A/R) from Dallas-Fort Worth to Shanghai and Beijing, as well as from Los Angeles and Dallas-Fort Worth to Hong Kong. DELTA had not adjusted its schedule of direct flights from the U.S. to China. It is the only airline with direct flights to not take action so far.

from fbprophet.diagnostics import cross_validation from fbprophet.diagnostics import performance_metrics

cross_validation_results = cross_validation(D_Model1, initial='3200 days', period='30 days', horizon='70 days') print(cross_validation_results)

performance_metrics_results = performance_metrics(cross_validation_results) print(performance_metrics_results)

In [68]:
#Calculating the highest and lowest spike in the forecasted values
start_date = '2020-05-28'
end_date = '2020-07-27'
mask = (dal2_forecast['ds'] > start_date) & (dal2_forecast['ds'] <= end_date)
dal2_forecast1 = dal2_forecast.loc[mask]
mask = (aal2_forecast['ds'] > start_date) & (aal2_forecast['ds'] <= end_date)
aal2_forecast1 = aal2_forecast.loc[mask]
mask = (luv2_forecast['ds'] > start_date) & (luv2_forecast['ds'] <= end_date)
luv2_forecast1 = luv2_forecast.loc[mask]
mask = (ual2_forecast['ds'] > start_date) & (ual2_forecast['ds'] <= end_date)
ual2_forecast1 = ual2_forecast.loc[mask]
In [69]:
def max_min(df):
    max1 = df['yhat'].max()
    min1 = df['yhat'].min()
    date_of_max = df[df['yhat'] == max1]['ds'].values[0]
    date_of_min = df[df['yhat'] == min1]['ds'].values[0]            
    print ('Max Stock Value in Billion$: ' + str(round(max1,2)) + ' on ' + str(date_of_max))
    print ('Min Stock Value in Billion$: ' + str(round(min1,2)) + ' on ' + str(date_of_min))
    profit_change = (max1-min1)/min1 * 100
    print ('profit change' + str(round(profit_change,2)) + ' %')
    return; 
In [70]:
max_min(dal2_forecast1)
Max Stock Value in Billion$: 15.59 on 2020-07-21T00:00:00.000000000
Min Stock Value in Billion$: 14.38 on 2020-05-29T00:00:00.000000000
profit change8.45 %
In [71]:
max_min(luv2_forecast1)
Max Stock Value in Billion$: 19.36 on 2020-07-27T00:00:00.000000000
Min Stock Value in Billion$: 15.18 on 2020-05-29T00:00:00.000000000
profit change27.53 %
In [72]:
max_min(aal2_forecast1)
Max Stock Value in Billion$: 4.37 on 2020-06-03T00:00:00.000000000
Min Stock Value in Billion$: 3.75 on 2020-07-24T00:00:00.000000000
profit change16.63 %
In [73]:
max_min(ual2_forecast1)
Max Stock Value in Billion$: 6.73 on 2020-07-21T00:00:00.000000000
Min Stock Value in Billion$: 6.14 on 2020-05-29T00:00:00.000000000
profit change9.72 %